#!/bin/bash
# Desc: 院长多功能防火墙管理脚本（支持firewalld/iptables）
# Author: 院长
# Web: https://deanit.cn
# Date: 2025-03-12

# 初始化变量
FIREWALL_TYPE=""
CONFIG_BACKUP_DIR="/var/firewall_backup"
IPTABLES_RULES_FILE="$CONFIG_BACKUP_DIR/iptables.rules"
FIREWALLD_ZONE_FILE="$CONFIG_BACKUP_DIR/firewalld_zones.xml"

# 检测root权限
check_root() {
  if [ "$EUID" -ne 0 ]; then
    echo "错误：必须使用root权限运行此脚本"
    exit 1
  fi
}

# 检测防火墙类型
detect_firewall() {
  if systemctl is-active --quiet firewalld; then
    FIREWALL_TYPE="firewalld"
  elif systemctl is-active --quiet iptables; then
    FIREWALL_TYPE="iptables"
  else
    echo "警告：未找到活动的防火墙服务，将尝试安装..."
    install_firewall
  fi
}

# 安装防火墙服务
install_firewall() {
  read -p "请选择要安装的防火墙类型 (1. firewalld 2. iptables): " choice
  case $choice in
  1)
    yum install -y firewalld
    systemctl enable --now firewalld
    FIREWALL_TYPE="firewalld"
    ;;
  2)
    yum install -y iptables-services
    systemctl enable --now iptables
    FIREWALL_TYPE="iptables"
    ;;
  *)
    echo "无效选择，退出..."
    exit 1
    ;;
  esac
}

# 防火墙状态管理
manage_service() {
  case $FIREWALL_TYPE in
  firewalld)
    systemctl $1 firewalld
    ;;
  iptables)
    systemctl $1 iptables
    ;;
  esac
}

# 通用端口操作
port_operation() {
  read -p "请输入端口号: " port
  read -p "请输入协议类型 (tcp/udp): " protocol

  case $1 in
  add)
    case $FIREWALL_TYPE in
    firewalld)
      firewall-cmd --permanent --add-port=$port/$protocol
      firewall-cmd --reload
      ;;
    iptables)
      iptables -A INPUT -p $protocol --dport $port -j ACCEPT
      service iptables save
      ;;
    esac
    ;;
  remove)
    case $FIREWALL_TYPE in
    firewalld)
      firewall-cmd --permanent --remove-port=$port/$protocol
      firewall-cmd --reload
      ;;
    iptables)
      iptables -D INPUT -p $protocol --dport $port -j ACCEPT
      service iptables save
      ;;
    esac
    ;;
  esac
}

# IP地址管理
ip_management() {
  read -p "请输入IP地址: " ip
  read -p "请输入操作类型 (allow/block): " action

  case $FIREWALL_TYPE in
  firewalld)
    if [ "$action" = "allow" ]; then
      firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='$ip' accept"
    else
      firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='$ip' reject"
    fi
    firewall-cmd --reload
    ;;
  iptables)
    if [ "$action" = "allow" ]; then
      iptables -A INPUT -s $ip -j ACCEPT
    else
      iptables -A INPUT -s $ip -j DROP
    fi
    service iptables save
    ;;
  esac
}

# NAT配置管理
nat_management() {
  case $1 in
  add)
    read -p "请输入内网接口: " internal_if
    read -p "请输入外网接口: " external_if
    iptables -t nat -A POSTROUTING -o $external_if -j MASQUERADE
    iptables -A FORWARD -i $external_if -o $internal_if -m state --state RELATED,ESTABLISHED -j ACCEPT
    iptables -A FORWARD -i $internal_if -o $external_if -j ACCEPT
    echo 1 >/proc/sys/net/ipv4/ip_forward
    service iptables save
    ;;
  remove)
    iptables -t nat -F POSTROUTING
    iptables -F FORWARD
    service iptables save
    ;;
  esac
}

# 端口转发
port_forward() {
  read -p "请输入源端口: " src_port
  read -p "请输入目标IP: " dest_ip
  read -p "请输入目标端口: " dest_port
  read -p "请输入协议类型 (tcp/udp): " protocol

  case $FIREWALL_TYPE in
  firewalld)
    firewall-cmd --permanent --add-forward-port=port=$src_port:proto=$protocol:toport=$dest_port:toaddr=$dest_ip
    firewall-cmd --reload
    ;;
  iptables)
    iptables -t nat -A PREROUTING -p $protocol --dport $src_port -j DNAT --to $dest_ip:$dest_port
    service iptables save
    ;;
  esac
}

# 配置备份
backup_config() {
  mkdir -p $CONFIG_BACKUP_DIR
  case $FIREWALL_TYPE in
  firewalld)
    firewall-cmd --runtime-to-permanent
    cp /etc/firewalld/zones/*.xml $CONFIG_BACKUP_DIR
    ;;
  iptables)
    iptables-save >$IPTABLES_RULES_FILE
    ;;
  esac
  echo "配置已备份至 $CONFIG_BACKUP_DIR"
}

# 配置恢复
restore_config() {
  case $FIREWALL_TYPE in
  firewalld)
    cp $CONFIG_BACKUP_DIR/*.xml /etc/firewalld/zones/
    firewall-cmd --reload
    ;;
  iptables)
    iptables-restore <$IPTABLES_RULES_FILE
    service iptables save
    ;;
  esac
  echo "配置已从备份恢复"
}

# 实时日志监控
monitor_logs() {
  echo "选择日志类型："
  echo "1. 实时防火墙日志"
  echo "2. 最近20条拒绝记录"
  read -p "请输入选择: " log_choice

  case $log_choice in
  1)
    tail -f /var/log/messages | grep -E 'iptables|firewalld'
    ;;
  2)
    journalctl -u $FIREWALL_TYPE | grep -i 'denied' | tail -n 20
    ;;
  *)
    echo "无效选择"
    ;;
  esac
}

# 显示菜单
show_menu() {
  clear
  echo "========================================"
  echo "  院长多功能防火墙管理脚本 ($FIREWALL_TYPE)"
  echo "========================================"
  echo "1. 启动防火墙服务"
  echo "2. 停止防火墙服务"
  echo "3. 重启防火墙服务"
  echo "4. 添加端口"
  echo "5. 删除端口"
  echo "6. IP白名单/黑名单管理"
  echo "7. NAT配置管理"
  echo "8. 端口转发配置"
  echo "9. 备份当前配置"
  echo "10. 恢复备份配置"
  echo "11. 查看防火墙状态"
  echo "12. 实时日志监控"
  echo "13. 切换防火墙类型"
  echo "0. 退出"
  echo "========================================"
}

# 主程序
main() {
  check_root
  detect_firewall

  while true; do
    show_menu
    read -p "请输入选项: " choice

    case $choice in
    1) manage_service start ;;
    2) manage_service stop ;;
    3) manage_service restart ;;
    4) port_operation add ;;
    5) port_operation remove ;;
    6) ip_management ;;
    7)
      echo "1. 添加NAT规则"
      echo "2. 删除NAT规则"
      read -p "请选择: " nat_choice
      [ "$nat_choice" = "1" ] && nat_management add
      [ "$nat_choice" = "2" ] && nat_management remove
      ;;
    8) port_forward ;;
    9) backup_config ;;
    10) restore_config ;;
    11)
      case $FIREWALL_TYPE in
      firewalld) firewall-cmd --list-all ;;
      iptables) iptables -L -n -v ;;
      esac
      ;;
    12) monitor_logs ;;
    13) install_firewall ;;
    0) exit 0 ;;
    *) echo "无效选项，请重新输入" ;;
    esac

    read -p "按回车键继续..."
  done
}

# 执行主程序
main
